#!/bin/sh
WKDIR=`dirname $0`
ISOFILES=""
MOUNTPOINT_ROOT=/tmp/iso
FDB=/tmp/fdb
LOG=/tmp/isorpm.log
VERSION=200903270958
DEPTMPF=/tmp/isorpm.tmp.$$

declare -a rpm_array

exit_on_error()
{
	echo "${1:-Error: program exits on error!}"
	echo 
	clear_tmpf
	exit 42
}

#
# mount iso files that are listed in ISOFILES var
#
_mount_iso()
{
	local i=0
	for f in $ISOFILES 
	do
		let i=$i+1
		mkdir -p $MOUNTPOINT_ROOT/$i || exit_on_error "Can't make mount point $MOUNTPOINT_ROOT/$i"
		#echo "mount $f ... "
		if mount | grep $MOUNTPOINT_ROOT/$i ; then
			echo "found $MOUNTPOINT_ROOT/$i alread mounted" | tee -a $LOG 2>&1 >/dev/null
		else
			mount -o loop $f $MOUNTPOINT_ROOT/$i||exit_on_error "Can't mount $f !"
		fi
	done
}

#
# unmount iso files that are listed in ISOFILES var
#
_umount_iso()
{
	local i=0
	for f in $ISOFILES 
	do
		let i=$i+1
		umount $MOUNTPOINT_ROOT/$i 2>&1 | tee -a $LOG >/dev/null
	done
}

#
# read configuratoin file to set ISOFILES var
#
scan_isofiles()
{
	local inifile="`basename $0`.ini"
	if [ -e $WKDIR/$inifile ]; then	
		ISOFILES=`cat $WKDIR/$inifile  | grep -i iso$ `
	else
		echo 
		echo "Missing configuration file($WKDIR/$inifile). You can make the ini file by the command below:"
		echo "  $ find abs_path_to_iso *.iso > isorpminstall.ini "
		echo "  eg. find /iso/suse/*.iso | grep -i ia64 > isorpminstall.ini"
		exit_on_error 
	fi
}

#
# build up the rpm files' db by find command
#
build_rpmdb()
{
	echo "Building rpmdb for the ISO files ..."
	_mount_iso
	>$FDB
	local i=0
	for f in $ISOFILES 
	do
		let i=$i+1
		find $MOUNTPOINT_ROOT/$i >> $FDB 
	done
	_umount_iso
	echo "Found total rpm records: `wc -l $FDB | awk '{print $1}' ` "

}

#
# search rpm file name in rpmdb by any keyword
#
search_rpm()
{
	local keyword="$1"
	#
	# Don't declare -a rpm_array here.
	# Use global rpm_array instead of local rpm_array 
	# because it will be used by install_rpm_by_number()
	#
	if [ -e $FDB ]; then
		rpm_array=($(grep $keyword $FDB))
		local n=0
		for r in ${rpm_array[*]}
		do
			let n=$n+1
			echo -e "$n\t$r"
		done
	else
		exit_on_error "Error: missing rpmdb file: $FDB"
	fi
}

#
# install rpm file
#
install_rpm_by_filename()
{
	_mount_iso
	local rpmfile=""
	for rpmfile in $*
	do
		rpm -i --test $rpmfile 
		if [ $? -eq  0 ]; then
			rpm -ivh $rpmfile 2>&1 | tee -a $LOG
		else
			#echo "Failed to install !!"
			crack_dependency $rpmfile
		fi
	done
	_umount_iso
	
}

#
# find out the depencies and install them
#------------------------
#dependency broken output
#------------------------
#error: Failed dependencies:
#	libext2fs-devel = 1.41.1 is needed by e2fsprogs-devel-1.41.1-13.4.ia64
#	libblkid-devel = 1.41.1 is needed by e2fsprogs-devel-1.41.1-13.4.ia64
#	libuuid-devel = 1.41.1 is needed by e2fsprogs-devel-1.41.1-13.4.ia64
crack_dependency()
{
	#echo "Crack Dependencies ..."
	local instfile=$1
	rpm -i --test $instfile 1>&2 2>$DEPTMPF | tee -a $LOG
	local depfiles=`cat $DEPTMPF | grep "needed by" | awk '{print $1}'`
	local dep=""
	
	for dep in $depfiles
	do
		grep $dep $FDB 2>&1 1>/dev/null
		if [ $? -ne 0 ]; then
			exit_on_error "Missing dependency file $dep in iso file "
		fi
		
		install_rpm_by_filename `grep $dep $FDB`	
	done	
}

#
#  install rpm by menu
#
install_rpm_by_number()
{
	declare -a selectionlist 
	declare -a ctrllist=(Quit)
	selectionlist=( ${rpm_array[@]} ${ctrllist[@]} )
	# debug values
	#echo  ${selectionlist[*]}
	# debug element count
	#echo ${#selectionlist[@]}

	echo 
	echo "--------------------------------------------------"
	echo "Search Result:"
	echo "--------------------------------------------------"
	export PS3="Choose Number: "

	select RPM in ${selectionlist[*]}
	do
	  case $RPM in
		Quit)	
			clear_tmpf
          		echo "Exit."
			break
			;;
        	*)
          		echo "  You picked $RPM ($REPLY)"
			install_rpm_by_filename $RPM
          		;;
  	  esac
	done
}

#
# delete temporary file
#
clear_tmpf()
{
	rm -f $DEPTMPF
}

#
# catch signal
#
my_trap()
{
	echo 
	clear_tmpf
	exit_on_error "User interminated."
}

usage()
{
	echo
	echo "usage: `basename $0` [-h][-v][m][u][-b] [-s <keyword>] [-i <rpmfile>] [-I]"
	echo " -h help"
	echo " -b build the rpmdb for the iso files"
	echo " -m mount the iso files only"
	echo " -u unmount the iso files only"
	echo " -i <rpmfile1 rpmfile2 rpmfile 3 ...> install the rpm file based on the info in rpmdb"
	echo " -I install rpm interactively, must with -s option together"
	echo " -s <keyword> search the word in rpmdb, must run -b first"
	echo " -v show version"
	echo 
	echo "Note: "
	echo "1. create ini file "
	echo "2. build up the rpmdb file "
	echo "3. search the keyword in rpm file names"
	echo "4. install the rpm file"
	echo "Repeat step 3 and step 4 for install rpm from the iso files"
}

# ============= main =======================

trap my_trap SIGINT SIGTERM

if [ $# -eq 0 ] ; then
	usage
	exit_on_error " "
fi

MOUNTCMD=""
UMOUNTCMD=""
BUILD=""
SKEY=""
INSTALL=""
INTERACTIVE=""
while getopts ":hvmubIs:i:" opt
do
	case $opt in
		h)	usage
			;;
		v)	echo "Version: $VERSION"
			exit 0
			;;
		m)	echo "mounting iso files ..."
			MOUNTCMD="y"
			;;
		u)	echo "umounting iso files ..."
			UMOUNTCMD="y"
			;;
		b)	BUILD="y"
			;;	
		s)	SKEY="$OPTARG"	
			;;
		i)	INSTALL="$OPTARG"	
			;;
		I)	INTERACTIVE="y"
			;;
		\?)	usage
			;;
	esac
done
shift $(($OPTIND - 1))

>$DEPTMPF
if [ x$ISOFILES = x ]; then
	scan_isofiles
fi

if [ ! x$MOUNTCMD = x ]; then
	_mount_iso
fi

if [ ! x$UMOUNTCMD = x ]; then
	_umount_iso
fi

if [ ! x$BUILD = x ]; then
	build_rpmdb
	exit 0
fi

if [ ! x$SKEY = x ] && [ x$INTERACTIVE = x ]; then
	search_rpm "$SKEY"	
	exit 0
fi

if [ ! x$SKEY = x ] && [ ! x$INTERACTIVE = x ]; then
	search_rpm "$SKEY" 2>&1 1>/dev/null
	install_rpm_by_number 
	exit 0
fi

if [ ! x$INSTALL = x ]; then
	install_rpm_by_filename "$INSTALL"
	exit 0
fi

clear_tmpf
